from ast import Tuple
import json
from pydantic import BaseModel, Field
from configparser import ConfigParser
from threading import RLock
import os
from typing import List, Dict, Any, Tuple


class ConfigManager:
    """
    参数管理器，管理分组参数并提供多线程安全支持。
    """

    _instance = None
    _lock = RLock()

    class Parameters(BaseModel):
        """
        用于存储参数的 Pydantic 数据模型，对应 system.ini 中的配置。
        """

        # FILE 组
        last_opened_file: str = Field(default="", description="最后打开的文件")
        open_bag_file: str = Field(default="", description="打开的bag文件路径")
        save_log_to_file: bool = Field(default=False, description="是否保存日志到文件")

        # LANGUAGE 组
        current_language: str = Field(default="zh_CN", description="当前语言")
        # THEME 组
        current_theme: str = Field(default="light", description="当前主题")
        
        # ROS 组
        bagversion: str = Field(default="new", description="Bag版本")
        version: str = Field(default="ROS1", description="ROS版本")
        vehicle: str = Field(default="f1-2.2c-3d", description="车辆类型")

        bagchange_progress:str = Field(
            default="",
            description="当前bag包转db过程信息"
        )
        
        # BAGLIST 组
        change_topic: List[str] = Field(
            default_factory=list,
            description="需要转换的话题列表"
        )
        localmap: str = Field(default="", description="本地地图文件路径")
        
        # SSHCONFIG 组
        port: int = Field(default=22, description="SSH端口")
        username: str = Field(default="", description="SSH用户名")
        password: str = Field(default="", description="SSH密码")
        ssh_remote_folder: str = Field(default="", description="SSH远程文件夹路径")
        
        # CAR_CALIBRATION_CHECK - 车辆校准检测结果
        car_calibration_check: Dict[str, Any] = Field(
            default_factory=lambda: {
                "system_version": "",
                "kernel_version": "",
                "mooe-core": "",
                "rslidar_points": False,
                "scan_init_down": False,
                "scan_down_left": False,
                "scan_down_right": False,
                "livox_lidar": False,
                "camera1_depth_points": False,
                "camera2_depth_points": False,
                "camera1_color_image_raw": False,
                "camera2_color_image_raw": False
            },
            description="车辆校准检测结果"
        )
        

        class Config:
            populate_by_name = True

    def __new__(cls, *args, **kwargs):
        """
        单例模式，确保全局只有一个 ConfigManager 实例。
        """
        with cls._lock:
            if cls._instance is None:
                cls._instance = super().__new__(cls)
        return cls._instance

    def __init__(self):
        self._lock = RLock()
        self.parameters = self.Parameters()
        self.config_file = None

    def load_config(self, config_file: str):
        """
        从配置文件加载参数，并保存配置文件路径以支持写回。
        :param config_file: 配置文件路径
        """
        self.config_file = config_file
        config = ConfigParser()
        if os.path.exists(config_file):
            config.read(config_file)

            # 读取 FILE 组
            if config.has_section("FILE"):
                self.parameters.last_opened_file = config.get("FILE", "last_opened_file", fallback=self.parameters.last_opened_file)
                self.parameters.save_log_to_file = config.getboolean("FILE", "save_log_to_file", fallback=self.parameters.save_log_to_file)

            # 读取 LANGUAGE 组
            if config.has_section("LANGUAGE"):
                self.parameters.current_language = config.get("LANGUAGE", "current_language", fallback=self.parameters.current_language)

            # 读取 THEME 组
            if config.has_section("THEME"):
                self.parameters.current_theme = config.get("THEME", "current_theme", fallback=self.parameters.current_theme)
            
            # 读取 ROS 组
            if config.has_section("ROS"):
                self.parameters.bagversion = config.get("ROS", "bagversion", fallback=self.parameters.bagversion)
                self.parameters.version = config.get("ROS", "version", fallback=self.parameters.version)
                self.parameters.vehicle = config.get("ROS", "vehicle", fallback=self.parameters.vehicle)
            
            # 读取 BAGLIST 组
            if config.has_section("BAGLIST"):
                change_topic_str = config.get("BAGLIST", "change_topic", fallback="[]")
                try:
                    self.parameters.change_topic = json.loads(change_topic_str)
                except json.JSONDecodeError:
                    self.parameters.change_topic = []
                self.parameters.localmap = config.get("BAGLIST", "localmap", fallback=self.parameters.localmap)
                
            # 读取 SSHCONFIG 组
            if config.has_section("SSHCONFIG"):
                self.parameters.port = config.getint("SSHCONFIG", "port", fallback=self.parameters.port)
                self.parameters.username = config.get("SSHCONFIG", "username", fallback=self.parameters.username)
                self.parameters.password = config.get("SSHCONFIG", "password", fallback=self.parameters.password)
                self.parameters.ssh_remote_folder = config.get("SSHCONFIG", "remote_folder", fallback=self.parameters.ssh_remote_folder)

    def save_config(self, key: str = None):
        """
        将当前参数保存回配置文件。
        :param key: 指定要保存的参数项，如果为 None 则保存所有参数。
        """
        if not self.config_file:
            raise ValueError("未设置配置文件路径，无法保存配置。")

        config = ConfigParser()

        # 先读取现有的配置文件
        config.read(self.config_file)

        # 确保节存在
        if not config.has_section("FILE"):
            config.add_section("FILE")
        if not config.has_section("LANGUAGE"):
            config.add_section("LANGUAGE")
        if not config.has_section("THEME"):
            config.add_section("THEME")
        if not config.has_section("ROS"):
            config.add_section("ROS")
        if not config.has_section("BAGLIST"):
            config.add_section("BAGLIST")
        if not config.has_section("SSHCONFIG"):
            config.add_section("SSHCONFIG")

        # 写入 FILE 组
        if key is None or key == "last_opened_file":
            config.set("FILE", "last_opened_file", str(self.parameters.last_opened_file or ""))
        if key is None or key == "save_log_to_file":
            config.set("FILE", "save_log_to_file", str(self.parameters.save_log_to_file).lower())

        # 写入 LANGUAGE 组
        if key is None or key == "current_language":
            config.set("LANGUAGE", "current_language", str(self.parameters.current_language or ""))

        # 写入 THEME 组
        if key is None or key == "current_theme":
            config.set("THEME", "current_theme", str(self.parameters.current_theme or ""))
        
        # 写入 ROS 组
        if key is None or key == "bagversion":
            config.set("ROS", "bagversion", str(self.parameters.bagversion or ""))
        if key is None or key == "version":
            config.set("ROS", "version", str(self.parameters.version or ""))
        if key is None or key == "vehicle":
            config.set("ROS", "vehicle", str(self.parameters.vehicle or ""))
        
        # 写入 BAGLIST 组
        if key is None or key == "change_topic":
            config.set("BAGLIST", "change_topic", json.dumps(self.parameters.change_topic))
        if key is None or key == "localmap":
            config.set("BAGLIST", "localmap", str(self.parameters.localmap or ""))
            
        # 写入 SSHCONFIG 组
        if key is None or key == "port":
            config.set("SSHCONFIG", "port", str(self.parameters.port))
        if key is None or key == "username":
            config.set("SSHCONFIG", "username", str(self.parameters.username or ""))
        if key is None or key == "password":
            config.set("SSHCONFIG", "password", str(self.parameters.password or ""))
        if key is None or key == "ssh_remote_folder":
            config.set("SSHCONFIG", "remote_folder", str(self.parameters.ssh_remote_folder or ""))

        with open(self.config_file, "w") as configfile:
            config.write(configfile)

    def get_param(self, key: str, default=None):
        """
        获取参数值。
        :param key: 参数名称
        :param default: 默认值
        :return: 参数值
        """
        with self._lock:
            if key not in self.parameters.model_fields:
                if default is not None:
                    return default
                raise KeyError(f"参数 {key} 不存在。")
            return getattr(self.parameters, key)

    def set_param(self, key: str, value, update_default=False):
        """
        更新参数值。
        :param key: 参数名称
        :param value: 新值
        """
        with self._lock:
            if key in self.parameters.model_fields:
                setattr(self.parameters, key, value)
            else:
                raise KeyError(f"参数 {key} 不存在，无法设置。")


if __name__ == "__main__":

    # from setting import initialize_parameters

    # # 初始化参数管理器
    # config_manager = initialize_parameters()

    # # 读取参数
    # print("最后打开的文件:", config_manager.get_param("last_opened_file"))
    # print("是否保存日志到文件:", config_manager.get_param("save_log_to_file"))

    # # 更新参数
    # config_manager.set_param("db_file_name", "mydatabase.db")
    # print("数据库文件名:", config_manager.get_param("db_file_name"))

    # # 保存参数到配置文件
    # config_manager.save_config()
    config_file = r"F:\桌面\MooeMars\code\rvizx\conf\config.ini"  # 配置文件路径
    config_manager = ConfigManager()
    # 加载配置文件中的参数
    config_manager.load_config(config_file)
    print(config_manager.get_param("db_file_path"))
    print(config_manager.get_param("last_opened_file"))
